#pragma once
#include "common.h"
#include "trace.h"
#include "config.h"
#include "counter.h"

class DramOP
{
public:
    word_t addr;
    int8_t size; /* Bytes */
    bool write;
    uint64_t id;
    static uint64_t dram_op_id;
    DramOP() : DramOP(0, 0, false) {}
    DramOP(word_t addr, int8_t size, bool write) : addr(addr), size(size), write(write)
    {
        id = dram_op_id++;
    }
    ~DramOP() {}
};

class Dram
{
public:
    virtual void reset() = 0;
    virtual bool send(DramOP *) = 0;
    virtual bool recv(DramOP *) = 0;
    virtual void run() = 0;
};

class PerfectDram : public Dram
{
public:
    PerfectDram() {}
    ~PerfectDram() {}
    void reset() override {}
    bool send(DramOP *) override { return true; }
    bool recv(DramOP *) override { return true; }
    void run() override {}
};

class BasicDram : public Dram
{
public:
    typedef std::tuple<DramOP *, uint64_t> DramReq;
    std::list<DramReq> reqs;
    uint64_t cycle = 0;
    BasicDram();
    ~BasicDram();
    void reset() override;
    bool send(DramOP *) override;
    bool recv(DramOP *) override;
    void run() override;
};